//
//  XCImageLoader.swift
//  XCFPSMonitor
//
//  Created by mac on 2025/2/18.
//

//
//  XCImageLoader.swift
//  XCFPSMonitor
//
//  Created by mac on 2025/2/18.
//

//
//  XCImageLoader.swift
//  XCFPSMonitor
//
//  Created by mac on 2025/2/18.
//

import Foundation
import UIKit

//图片加载
class XCImageLoader {
    private var imageCache = NSCache<NSString, UIImage>() // 内存缓存
    private let operationQueue = OperationQueue()
    
    // 磁盘缓存路径
    private var diskCacheUrl: URL {
        let cachesDirectory = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!
        return cachesDirectory.appendingPathComponent("ImageCache")
    }
    
    private init() {
        // 创建磁盘缓存目录
        try? FileManager.default.createDirectory(at: diskCacheUrl, withIntermediateDirectories: true)
        operationQueue.maxConcurrentOperationCount = 5 // 设置最大并发数量为 5
    }
    
    // 加载图片方法
    func loadImage(from url: URL, targetSize: CGSize?, completion: @escaping (UIImage) -> Void) {
        let urlString = url.absoluteString
        
        // 检查内存缓存
        if let cacheImage = imageCache.object(forKey: urlString as NSString) {
            completion(targetSize.flatMap { resizeImage(cacheImage, targetSize: $0) } ?? cacheImage)
            return
        }
        
        // 检查磁盘缓存
        if let diskImage = loadImageFromDisk(named: url.lastPathComponent) {
            imageCache.setObject(diskImage, forKey: urlString as NSString)
            completion(targetSize.flatMap { resizeImage(diskImage, targetSize: $0) } ?? diskImage)
            return
        }
        
        // 创建下载操作
        let operation = ImageLoaderOperation(url: url) { [weak self] image in
            if let image = image {
                self?.imageCache.setObject(image, forKey: urlString as NSString)
                completion(targetSize.flatMap { self?.resizeImage(image, targetSize: $0) } ?? image)
            } else {
                completion(UIImage()) // 返回一个空的 UIImage 或者处理错误
            }
        }
        
        operation.queuePriority = .high
        operationQueue.addOperation(operation)
    }
    
    // 适用于 tableViewCell 快速滑动
    func loadImageWithPriority(from url: URL, completion: @escaping (UIImage?) -> Void) {
        operationQueue.cancelAllOperations() // 取消所有当前操作
        loadImage(from: url, targetSize: nil, completion: completion)
    }
    
    // 从磁盘加载图片
    private func loadImageFromDisk(named imageName: String) -> UIImage? {
        let fileURL = diskCacheUrl.appendingPathComponent(imageName)
        return UIImage(contentsOfFile: fileURL.path)
    }
    
    // 缩放和裁剪图片
    private func resizeImage(_ image: UIImage?, targetSize: CGSize) -> UIImage? {
        guard let image = image else { return nil }
        
        let size = image.size
        let scaleFactor = min(targetSize.width / size.width, targetSize.height / size.height)
        let newSize = CGSize(width: size.width * scaleFactor, height: size.height * scaleFactor)
        
        UIGraphicsBeginImageContextWithOptions(newSize, false, 0.0)
        image.draw(in: CGRect(origin: .zero, size: newSize))
        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        
        return newImage
    }
}

//利用operation自动管理，先进先出
class ImageLoaderOperation: Operation {
    private let url: URL
    private let completion: (UIImage?) -> Void
    private var task: URLSessionDataTask?
    
    init(url: URL, completion: @escaping (UIImage?) -> Void) {
        self.url = url
        self.completion = completion
    }
    
    override func main() {
        if isCancelled { return }
        
        // 下载图片
        task = URLSession.shared.dataTask(with: url) { [weak self] data, response, error in
            guard let self = self else { return }
            if self.isCancelled { return }
            
            let image = data.flatMap { UIImage(data: $0) }
            DispatchQueue.main.async {
                self.completion(image)
            }
        }
        
        task?.resume()
    }
    
    override func cancel() {
        super.cancel()
        task?.cancel()
    }
}
